package com.jc.gateway.filter;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jc.gateway.domain.CustomerApiSecret;
import com.jc.gateway.service.impl.SecretService;
import com.jc.util.HttpPostUtil;
import com.jc.util.R;

import com.jc.util.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

@Component
@Slf4j
public class AccessUtils {


    @Autowired
    private SecretService secretService;



    private ObjectMapper objectMapper = new ObjectMapper();


    private String getSign(String secretId, String secretKey, long timestamp) {
        return DigestUtils.md5Hex(secretId + timestamp + secretKey);
    }



    public Result<Void> validateFromHeaders(String secretId, String sign, long timestamp) {
        Result<Void> result = new Result<Void>().error();
        result.setCode(R.RCODE.SIGN_ERROR.getCode());

        if (secretId == null || sign == null) {
            result.setCode(R.RCODE.PARAMETERS_ERROR.getCode());
            result.setMessage(R.RCODE.PARAMETERS_ERROR.getMessage());
            return result;
        }

        CustomerApiSecret secretDTO = secretService.findById(secretId);
        if (secretDTO == null) {
            log.warn("Secret not found for secretId: {}", secretId);
            result.setCode(R.RCODE.SIGN_ERROR.getCode());
            result.setMessage(R.RCODE.SIGN_ERROR.getMessage());
            return result;
        }

        String sourceSign = getSign(secretDTO.getSecretId(), secretDTO.getSecretKey(), timestamp);
        if (!sourceSign.equals(sign)) {
            log.warn("Signature mismatch for secretId: {}", secretId);
//            result.setMessage("Signature verification failed");
            result.setCode(R.RCODE.SIGN_ERROR.getCode());
            result.setMessage(R.RCODE.SIGN_ERROR.getMessage());
            return result;
        }

        // 检查时间戳有效性（可选）
//        long currentTime = System.currentTimeMillis();
//        long timeDiff = Math.abs(currentTime - timestamp);
//        if (timeDiff > 5 * 60 * 1000) { // 5分钟有效期
//            log.warn("Timestamp expired: {}", timestamp);
//            result.setMessage("Request expired");
//            return result;
//        }

        return new Result<Void>().ok();
    }



    public Result<String> decode(String data, String uri) {
        // 如果是文件上传请求直接放行
        if (uri.contains("/fileUpload/")) {
            return new Result<String>().ok(data);
        }

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        Result<String> result = new Result<String>().error();
        result.setCode(R.RCODE.SIGN_ERROR.getCode());
        try {
            Map<String, Object> map = objectMapper.readValue(data, Map.class);
            Long timestamp = Long.valueOf(String.valueOf(map.get(HttpPostUtil.TIMESTAMP)));
//			//生产环境校验需要放开
//			if(System.currentTimeMillis() - timestamp > timeOutMin* 60 *1000){
//				logger.info("Access timeout!");
//				return new R<String>().error(R.RCODE.SIGN_ERROR, "time out " + timeOutMin + " minutes");
//			}
            if (!map.containsKey(HttpPostUtil.SECRETID)){
                Result re = new Result<String>().error();
                re.setCode(R.RCODE.PARAMETERS_ERROR.getCode());
                re.setMessage(R.RCODE.PARAMETERS_ERROR.getMessage());
                re.setContent(JSONUtil.toBean(data, Map.class));
                return re;
            }
            String secretId = map.get(HttpPostUtil.SECRETID).toString();

            CustomerApiSecret secretDTO = secretService.findById(secretId);

            if (secretDTO == null) {
                log.warn("select secret is null");
                Result re = new Result<String>().error();
                re.setCode(R.RCODE.SIGN_ERROR.getCode());
                re.setMessage(R.RCODE.SIGN_ERROR.getMessage());
                re.setContent(JSONUtil.toBean(data, Map.class));
                return re;
            }
            String sourceSign = getSign(secretDTO.getSecretId(), secretDTO.getSecretKey(), timestamp);
            String sign = map.get(HttpPostUtil.SIGN).toString();
            // 生产环境校验需要放开
            if (!sourceSign.equals(sign)) {
                log.warn("sourceSign and sign is different");
                Result re = new Result<String>().error();
                re.setCode(R.RCODE.SIGN_ERROR.getCode());
                re.setMessage(R.RCODE.SIGN_ERROR.getMessage());
                re.setContent(JSONUtil.toBean(data, Map.class));
                return re;
            }
//			List<Map<String, String>> dataJsons = null;
//			Object obj = map.get(HttpPostUtil.DATALIST);
//			if(obj instanceof String) {
//				String dataStr = obj.toString();
//				dataJsons = objectMapper.readValue(dataStr, List.class);
//			} else if(obj instanceof List) {
//				dataJsons = (List<Map<String, String>>) map.get(HttpPostUtil.DATALIST);
//			}
//			if(null==dataJsons || dataJsons.isEmpty()) {
//				Object o = map.get(HttpPostUtil.DATA);
//				Map<String, Object> newMap = null;
//				if(o instanceof Map) {
//					newMap = (Map<String, Object>) o;
//				} else {
//					String dataJson = o.toString();
//					newMap = objectMapper.readValue(dataJson, Map.class);
//				}
//
//				this.trimStr(newMap);
//				result = new Result<String>().ok(objectMapper.writeValueAsString(newMap));
//			} else {
//				String dateStr = objectMapper.writeValueAsString(dataJsons);
//				result = new Result<String>().ok(dateStr);
//			}
            result = new Result<String>().ok(data);
        } catch (IOException e) {
            log.error("read post map error" + e.getMessage(), e);
            result.error();
            result.setMessage("read post map error" + e.getMessage());
            return result;
        }
        return result;
    }

//	private void trimStr(Map<String, Object> newMap) {
//		Set<Map.Entry<String, Object>> entries = newMap.entrySet();
//		for (Map.Entry<String, Object> entry : entries) {
//			String key = entry.getKey();
//			Object value = entry.getValue();
//			if (value instanceof String) {
//				value = StrUtil.trim(String.valueOf(value));
//				newMap.put(key,value);
//			}
//			if (value instanceof Map) {
//				this.trimStr((Map<String, Object>) value);
//			}
//			if (value instanceof List) {
//				List list = (List) value;
//				for (Object o : list) {
//					if (o instanceof String) {
//						value = StrUtil.trim(String.valueOf(value));
//					}else{
//						this.trimStr((Map<String, Object>) o);
//					}
//				}
//			}
//		}
//	}
}